package com.gpj.sqlbuilder;

import com.gpj.sqlbuilder.converters.ExcelConverter;
import com.gpj.sqlbuilder.converters.TemplateConverter;
import com.gpj.sqlbuilder.io.ExcelReader;
import com.gpj.sqlbuilder.io.SqlWriter;
import com.gpj.sqlbuilder.store.common.TemplateWraper;
import com.gpj.sqlbuilder.store.excel.Sheet;
import com.gpj.sqlbuilder.store.sql.Table;
import com.gpj.sqlbuilder.template.Template;
import com.gpj.sqlbuilder.utils.JarIOUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @className SQLToolApplication
 * @description
 *   TODO
 * @author GPJ
 * @date 2021/3/26 14:58
 * @version 1.0
 **/
@Slf4j
public class SQLToolApplication {
    private ExcelReader reader = new ExcelReader();
    private ExcelConverter excelConverter = new ExcelConverter();
    private TemplateConverter templateConverter = new TemplateConverter();
    private SqlWriter writer = new SqlWriter();
    
    public void run(String workspace, String excelName){
        URL url = RunApplication.class.getResource("");
        String protocol = url.getProtocol();
        if("jar".equals(protocol)){ // jar 中运行
            workspace = StringUtils.isBlank(workspace) ? JarIOUtil.getJarDir() : workspace;
            excelName = StringUtils.isBlank(excelName) ? "db.xlsx" : excelName;
        }else if("file".equals(protocol)){// 非 jar 中云心
            File dir = new File(RunApplication.class.getClassLoader().getResource("").getPath());
            File file = new File(dir.getParent(), "classes");

            workspace = StringUtils.isBlank(workspace) ? file.getPath() : workspace;
            excelName = StringUtils.isBlank(excelName) ? "db.xlsx" : excelName;
        }

        if(workspace.endsWith("/")) workspace = workspace.substring(0, workspace.length() - 1);
        if(workspace.endsWith("\\")) workspace = workspace.substring(0, workspace.length() - 1);

        log.info("工作目录:{}", workspace);
        log.info("数据库定义文件名:{}", excelName);

        Map<String, Sheet> sheetMap = reader.read(workspace + "/" + excelName);
        if(sheetMap == null || sheetMap.isEmpty()){
            resultInfo(false);
            return;
        }
        log.info("");

        List<Table> tables = excelConverter.convert(sheetMap);
        if(tables.isEmpty()){
            resultInfo(false);
            return;
        }
		showTableInfo(tables);

        log.info("-- 解析模板 开始 -- ");
        String[] templateFiles = {"table.template", "datas.template"};
        List<TemplateWraper> templates = new ArrayList();
        for (String templateFile : templateFiles) {
            InputStream io = this.getClass().getResourceAsStream("/mysql/" + templateFile);
            assert  io != null;
            TemplateWraper template = templateConverter.convert(templateFile, io);
            showTemplateInfo(template);
            templates.add(template);
        }
        log.info("-- 解析模板 结束 -- ");

        log.info("-- 生成sql 开始 -- ");
        for (TemplateWraper template : templates) {
            log.debug("\t-- [{}]表sql -- ", template.getTemplateFileName());
            writer.writ(workspace, template, tables);
            log.debug("\t-- [{}]表sql -- ", template.getTemplateFileName());
        }
        log.info("-- 生成sql 结束 -- ");

    }

    private void resultInfo(boolean success) {
        log.info("-------------------");
        log.info("脚本生成{}", success?"成功":"失败");
        log.info("-------------------");
    }

    private void showTableInfo(List<Table> tables) {
        log.info("-- 建表数据 -- ");
        tables.forEach(table -> {
            log.info("\ttable\t| {}", table.getName());
            log.info("\tcolumns\t| {}", table.getColumns().stream()
                    .map(column -> column.getName()).collect(Collectors.joining(",")));
        });
        log.info("-- 建表数据 -- ");
    }

    private void showTemplateInfo(TemplateWraper template) {
        log.debug("\t-- 模板[{}]解析结果 -- ", template.getTemplateFileName());
        templateLog(template.getRoot(), 2);
        log.debug("\t-- 模板[{}]解析结果 -- ", template.getTemplateFileName());
    }

    private void templateLog(Template template, int level){
        StringBuffer tab = new StringBuffer();
        for (int i = 0; i < level; i++) {
            tab.append("\t");
        }
        log.debug("{}{}", tab.toString(), template.toString());

        for (Template child : template.getChildren()) {
            templateLog(child, level + 1);
        }
    }

}
